home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / src / dcpp / define.c < prev    next >
C/C++ Source or Header  |  1997-09-09  |  14KB  |  601 lines

  1. /*
  2.  *    (c)Copyright 1992-1997 Obvious Implementations Corp.  Redistribution and
  3.  *    use is allowed under the terms of the DICE-LICENSE FILE,
  4.  *    DICE-LICENSE.TXT.
  5.  */
  6.  
  7. /*
  8.  *  DEFINE.C
  9.  *
  10.  */
  11.  
  12. #include "defs.h"
  13. #ifdef AMIGA
  14. #include "/dc1/tokens.h"
  15. #else
  16. #include "../dc1/tokens.h"
  17. #endif
  18.  
  19. Prototype void InitDefines(char *);
  20. Prototype void ModifySymbolText(Sym *, short);
  21. Prototype void do_undef(ubyte *, int, long *);
  22. Prototype void do_define(ubyte *, int, long *);
  23. Prototype long PreliminaryReplace(char *, long, char **, short *, short, char **);
  24. Prototype Include * PrepareSymbolArgs(Sym *, ubyte *, long *, long);
  25. Prototype long HandleSymbol(Sym *, ubyte *, long, long);
  26.  
  27. #define  X_LINE         (SF_SPECIAL|0x100)
  28. #define  X_DATE         (SF_SPECIAL|0x200)
  29. #define  X_FILE         (SF_SPECIAL|0x300)
  30. #define  X_BASE_FILE        (SF_SPECIAL|0x400)
  31. #define  X_TIME         (SF_SPECIAL|0x500)
  32.  
  33. static char SymBaseFileBuf[256];
  34. static char SymFileBuf[256];
  35. static char SymLineBuf[16];
  36. static char SymDateBuf[64];
  37. static char SymTimeBuf[64];
  38.  
  39. void
  40. InitDefines(master)
  41. char *master;
  42. {
  43.     time_t t;
  44.     char *ct;
  45.     struct tm *tp;
  46.  
  47.     time(&t);
  48.     tp = localtime(&t);
  49.     ct = ctime(&t);
  50.  
  51.     sprintf(SymBaseFileBuf, "\"%s\"", master);
  52.     sprintf(SymDateBuf, "\"%.7s%.4s\"", ct + 4, ct + 20);
  53.     sprintf(SymDateBuf + 32, "\"%d.%d.%d\"", tp->tm_mday, tp->tm_mon + 1, tp->tm_year % 100);
  54.     sprintf(SymTimeBuf, "\"%.8s\"", ct + 11);
  55.  
  56.     if (StripOpt == 0) {
  57.     DefineSimpleSymbol("__LINE__",      SymLineBuf, X_LINE);
  58.     DefineSimpleSymbol("__DATE__",      SymDateBuf, 0);
  59.     DefineSimpleSymbol("__TIME__",      SymTimeBuf, 0);
  60.     DefineSimpleSymbol("__FILE__",      SymFileBuf, X_FILE);
  61.     DefineSimpleSymbol("__BASE_FILE__", SymBaseFileBuf, 0);
  62.  
  63.     DefineSimpleSymbol("__COMMODORE_DATE__", SymDateBuf + 32, 0);
  64.  
  65.     if (UndefSyms == 0) {
  66.         DefineSimpleSymbol("__STDC__",  "1", 0);
  67.         DefineSimpleSymbol("mc68000",   "1", 0);
  68.         DefineSimpleSymbol("_DCC",      "1", 0);
  69.         DefineSimpleSymbol("AMIGA",     "1", 0);
  70.     }
  71.     if (FFPDef)
  72.         DefineSimpleSymbol("_FFP_FLOAT","1", 0);
  73.     else
  74.         DefineSimpleSymbol("_SP_FLOAT", "1", 0);
  75.     }
  76. }
  77.  
  78. void
  79. ModifySymbolText(Sym *sym, short type)
  80. {
  81.     Include *inc = GetNominalInclude(0);
  82.  
  83.     switch(type) {
  84.     case X_FILE:
  85.     if (inc->FileName)
  86.         sprintf(SymFileBuf, "\"%s\"", inc->FileName);
  87.     else
  88.         sprintf(SymFileBuf, "\"<unknown>\"");
  89.     sym->TextLen = strlen(sym->Text);
  90.     break;
  91.     case X_LINE:
  92.     sprintf(SymLineBuf, "%ld", inc->LineNo);
  93.     sym->TextLen = strlen(SymLineBuf);
  94.     break;
  95.     }
  96. }
  97.  
  98. void
  99. do_undef(buf, max, pu)
  100. ubyte *buf;
  101. int max;
  102. long *pu;   /*    unused    */
  103. {
  104.     long n = ExtSymbol(buf, 0, max);
  105.  
  106.     if (n)
  107.     UndefSymbol(buf, n);
  108.     else
  109.     cerror(EERROR_UNDEF_NO_SYMBOL);
  110. }
  111.  
  112. void
  113. do_define(buf, max, pu)
  114. ubyte *buf;
  115. int max;
  116. long *pu;   /*    unused    */
  117. {
  118.     int i;
  119.     int b;
  120.     int symLen;
  121.     int numArgs = -1;
  122.     char *repBuf;
  123.     long repSize;
  124.     short alloc = 0;
  125.     static char *Args[MAX_ARGS];
  126.     static short Lens[MAX_ARGS];
  127.  
  128.     symLen = ExtSymbol(buf, 0, max);    /*  extract symbol  */
  129.     b = symLen;
  130.  
  131.     if (b < max && buf[b] == '(') {
  132.     numArgs = 0;
  133.  
  134.     ++b;
  135.     while (b < max && buf[b] != ')') {
  136.         while (b < max && WhiteSpace[buf[b]])   /*    skip ws     */
  137.         ++b;
  138.         i = ExtSymbol(buf, b, max);         /*    symbol name */
  139.         if (i == b) {
  140.         cerror(EERROR_ILLEGAL_NULL_SYMBOL);
  141.         return;
  142.         }
  143.         if (numArgs == MAX_ARGS)
  144.         cerror(EFATAL_MAX_MACRO_ARGS, MAX_ARGS);
  145.         Args[numArgs] = buf + b;
  146.         Lens[numArgs] = i - b;
  147.         ++numArgs;
  148.         dbprintf(("Macro Argument: %.*s\n", i -b, buf + b));
  149.  
  150.         b = i;
  151.         while (b < max && WhiteSpace[buf[b]])
  152.         ++b;
  153.         if (b >= max || (buf[b] != ')' && buf[b] != ',')) {
  154.         cerror(EERROR_EXPECTED_COMMA);
  155.         return;
  156.         }
  157.         if (b < max && buf[b] == ',')
  158.         ++b;
  159.     }
  160.     if (b >= max || buf[b] != ')') {
  161.         cerror(EERROR_EXPECTED_CLOSE_PAREN);
  162.         return;
  163.     }
  164.     ++b;
  165.     }
  166.     while (b < max && WhiteSpace[buf[b]])    /*  skip white space to macro body  */
  167.     ++b;
  168.  
  169.     /*
  170.      *    Lens and Args are modified, a new buffer and buffer size is returned.
  171.      *
  172.      *    If a simple macro (no arguments), just tell DefineSymbol() to allocate
  173.      *    a copy of the text buffer (which can go away since we free file buffers)
  174.      */
  175.  
  176.     if (numArgs > 0) {
  177.     repSize = PreliminaryReplace(buf + b, max - b, Args, Lens, numArgs, &repBuf);
  178.     } else {
  179.     repSize = max - b;
  180.     repBuf    = buf + b;
  181.     alloc = 1;
  182.     }
  183.  
  184.     /*
  185.      *    Define the symbol
  186.      */
  187.  
  188.     DefineSymbol(buf, symLen, 0, numArgs, Args, Lens, repBuf, 1, alloc, repSize);
  189. }
  190.  
  191. /*
  192.  *  Do argument replace and create identifiers for the macro arguments that are
  193.  *  not normal symbols.  "+%08lx"
  194.  */
  195.  
  196. #define TS_SIZE 9
  197.  
  198. long
  199. PreliminaryReplace(
  200.     char *src,
  201.     long max,
  202.     char **args,
  203.     short *lens,
  204.     short n,
  205.     char **pdst
  206. ) {
  207.     long i;
  208.     long di;
  209.     long bytes;
  210.     short j;
  211.     char *dst;
  212.     static long XId;    /*  replacement id. */
  213.     static char Tmp[MAX_ARGS][16];
  214.  
  215.     for (j = 0; j < n; ++j)
  216.     sprintf(Tmp[j], "\001%08lx", XId + j);  /*  TS_SIZE */
  217.  
  218.     /*
  219.      *    pass 1 : find symbols to replace and figure out the size of the new
  220.      *         buffer.
  221.      */
  222.  
  223.     bytes = max;
  224.     for (i = 0; i < max; ) {
  225.     ubyte c = src[i];
  226.  
  227.     if ((c < '0' || c > '9') && SymbolChar[c]) {
  228.         long l = ExtSymbol(src, i, max);
  229.         short len = l - i;
  230.  
  231.         for (j = 0; j < n; ++j) {
  232.         if (lens[j] == len && strncmp(args[j], src + i, len) == 0) {
  233.             bytes -= len;
  234.             bytes += TS_SIZE;
  235.             dbprintf(("MATCH %d\n", len));
  236.             break;
  237.         }
  238.         }
  239.         i = l;
  240.     } else if (c == '\"') {
  241.         i = SkipString(src, i + 1, max);
  242.     } else if (c == '\'') {
  243.         i = SkipSingleSpec(src, i + 1, max);
  244.     } else {
  245.         ++i;
  246.     }
  247.     }
  248.  
  249.     /*
  250.      *    pass 2, do replacement
  251.      */
  252.  
  253.     dbprintf(("replace buffer: %ld/%ld\n", max, bytes));
  254.  
  255.     if (bytes < 16)
  256.     dst = zalloc(bytes+1);        /*    efficiency only     */
  257.     else
  258.     dst = malloc(bytes+1);        /*    +1 necessary? don't think so... */
  259.     if (dst == NULL)
  260.     ErrorNoMemory();
  261.  
  262.     for (i = di = 0; i < max && di < bytes;) {
  263.     ubyte c = src[i];
  264.  
  265.     if ((c < '0' || c > '9') && SymbolChar[c]) {
  266.         long l = ExtSymbol(src, i, max);
  267.         short len = l - i;
  268.  
  269.         for (j = 0; j < n; ++j) {
  270.         if (lens[j] == len && strncmp(args[j], src + i, len) == 0) {
  271.             dbprintf(("MATCH %d\n", len));
  272.             break;
  273.         }
  274.         }
  275.         if (j == n) {   /*    not a replace symbol    */
  276.         movmem(src + i, dst + di, len);
  277.         i += len;
  278.         di += len;
  279.         } else {        /*    is a replace symbol    */
  280.         movmem(Tmp[j], dst + di, TS_SIZE);
  281.         i += len;
  282.         di += TS_SIZE;
  283.         dbprintf(("match len %d (%d/%d)\n", len, j, n));
  284.         }
  285.     } else if (c == '\"') {
  286.         long nn = i;
  287.         i = SkipString(src, i + 1, max);
  288.         movmem(src + nn, dst + di, i - nn);
  289.         di += i - nn;
  290.     } else if (c == '\'') {
  291.         long nn = i;
  292.         i = SkipSingleSpec(src, i + 1, max);
  293.         movmem(src + nn, dst + di, i - nn);
  294.         di += i - nn;
  295.     } else {
  296.         dst[di++] = c;
  297.         ++i;
  298.     }
  299.     }
  300.     if (i != max || di != bytes)
  301.     cerror(EFATAL_SOFT_ERROR_REPLACE, i, max, di, bytes);
  302.  
  303.     XId += n;
  304.  
  305.     for (j = 0; j < n; ++j) {
  306.     lens[j] = TS_SIZE;
  307.     args[j] = Tmp[j];
  308.     }
  309.  
  310.     *pdst = dst;
  311.     return(bytes);
  312. }
  313.  
  314. Include *PrepareSymbolArgs(sym, base, ip, max)
  315. Sym *sym;
  316. ubyte *base;
  317. long *ip;
  318. long max;  /* Set it negative to avoid doing any dumps */
  319. {
  320.     short oldType = sym->Type;
  321.     Include *push = PushBase;
  322.     long i  = *ip;
  323.     /* long oi = i;    **  position in original pushbase (not used)   */
  324.     long xi = i;    /*  position in followed pushbase   */
  325.     short candump = 1;
  326.  
  327.     if (max < 0)
  328.     {
  329.        max = -max;
  330.        candump = 1;
  331.     }
  332.  
  333.     if ((sym->Type & SF_SPECIAL) == 0) {
  334.     if (sym->Type & SF_RECURSE) {
  335.         cerror(EERROR_RECURSIVE_MACRO, sym->SymName);
  336.         push->Index = i;
  337.         return(NULL);
  338.     }
  339.     sym->Type |= SF_RECURSE;
  340.     }
  341.  
  342.     if (sym->NumArgs >= 0) {    /*  overload symbol args symbols    */
  343.     short j;
  344.                 /*  look for '('    */
  345.     for (;;) {
  346.         while (i < max && WhiteSpace[base[i]])
  347.         ++i;
  348.         if (i >= max || base[i] != '\n')
  349.         break;
  350.         ++PushBase->LineNo;
  351.         ForceLineSpec = 1;
  352.         ++i;
  353.     }
  354.     while (i >= max) {
  355.         push->Index = i;
  356.         if (push->IsFile)
  357.         cerror(EWARN_MACRO_CROSSES_INCLUDE);
  358.         if ((push = push->Next) == NULL) {
  359.         cerror(EERROR_UNEXPECTED_EOF_MACRO, sym->SymName);
  360.         sym->Type = oldType;
  361.         push->Index = i;
  362.         return(NULL);
  363.         }
  364.         xi = i = push->Index;
  365.         max = push->MaxIndex;
  366.         base = push->Base;
  367.         dbprintf(("SKIPBACK %ld/%ld %08lx\n", i, max, (unsigned long)base));
  368.     }
  369.  
  370.     /*
  371.      *  If no open-paren found then not a macro!
  372.      *
  373.      *  #define fubar(a,b)    hi!
  374.      *  ...     int fubar;
  375.      *
  376.      */
  377.  
  378.     if (base[i] != '(') {
  379.         sym->Type = oldType;
  380.         if (push)
  381.         push->Index = i;
  382.         if (candump)
  383.         {
  384.         Dump(sym->SymName, 0, sym->SymLen);
  385.         Dump(base, xi, i);
  386.         }
  387.         if (push)
  388.         push->Index = i;
  389.         *ip = PushBase->Index;
  390.         return(NULL);
  391.     }
  392.     ++i;
  393.  
  394.     /*
  395.      *  scan macro arguments.  Macro arguments are valid only at the
  396.      *  very next level, determined by setting
  397.      */
  398.  
  399.     for (j = 0; j < sym->NumArgs; ++j) {
  400.         short parens = 0;    /*  paren level     */
  401.         long b;        /*  base of argument    */
  402.  
  403.         while (i < max && WhiteSpace[base[i]])
  404.         ++i;
  405.         b = i;
  406.  
  407.         while (i < max) {
  408.         short c = base[i];
  409.  
  410.         if (c == ',' && parens == 0)
  411.             break;
  412.         if (c == '(') {
  413.             ++parens;
  414.             ++i;
  415.         } else if (c == ')') {
  416.             if (parens == 0)
  417.             break;
  418.             --parens;
  419.             ++i;
  420.         } else if (c == '\"') {
  421.             i = SkipString(base, i + 1, max);
  422.         } else if (c == '\'') {
  423.             i = SkipSingleSpec(base, i + 1, max);
  424.         } else if (c == '\n') {
  425.             if (push)
  426.             ++push->LineNo;
  427.             ForceLineSpec = 1;
  428.             ++i;
  429.         } else if (c == '/' && base[i+1] == '*') {
  430.             i = SkipComment(base, i + 2, max);
  431.         } else {
  432.             ++i;
  433.         }
  434.         }
  435.         dbprintf(("break-out %ld %c\n", i, base[i]));
  436.  
  437.         {
  438.         Sym *asym;
  439.         asym = DefineSymbol(
  440.                 sym->Args[j],
  441.                 sym->ArgsLen[j],
  442.                 SF_MACROARG,
  443.                 -1,
  444.                 NULL, NULL, base + b, 0, 0, i - b
  445.             );
  446.         asym->Creator = sym;
  447.         }
  448.  
  449.         while (push && i >= max) {
  450.         if (push->IsFile)
  451.             cerror(EWARN_MACRO_CROSSES_INCLUDE);
  452.         push->Index = i;
  453.         if ((push = push->Next) == NULL)
  454.             break;
  455.         i = push->Index;
  456.         max = push->MaxIndex;
  457.         base = push->Base;
  458.         }
  459.  
  460.         if (i < max && base[i] == ',') {
  461.         ++i;
  462.         continue;
  463.         }
  464.  
  465.         while (push && i >= max) {
  466.         push->Index = i;
  467.         if ((push = push->Next) == NULL)
  468.             break;
  469.         i = push->Index;
  470.         max = push->MaxIndex;
  471.         base = push->Base;
  472.         }
  473.  
  474.         if (i >= max || base[i] != ')') {
  475.         cerror(EERROR_EXPECTED_COMMA_CLOSE);
  476.         break;
  477.         }
  478.     }
  479.     if (j != sym->NumArgs) {
  480.         cerror(EERROR_NOT_ENOUGH_ARGS_MACRO, j, sym->NumArgs);
  481.         while (--j >= 0)
  482.         UndefSymbol(sym->Args[j], sym->ArgsLen[j]);
  483.         sym->Type = oldType;
  484.         if (push)
  485.         push->Index = i;
  486.         return(NULL);
  487.     }
  488.     if (base[i] != ')') {
  489.         cerror(EERROR_EXPECTED_CLOSE_PAREN_ARG, sym->SymName);
  490.     } else {
  491.         ++i;
  492.     }
  493.     }
  494.     if (push)
  495.     push->Index = i;
  496.     *ip = i;
  497.     return(push);
  498. }
  499.  
  500. /*
  501.  *  Handle special symbol.  Replacement stuff has been stripped of comments.
  502.  *  Must rescan to handle other macros and such.
  503.  *
  504.  *    symbol        -> replace-stuff    sym->NumArgs < 0
  505.  *    symbol(args)    -> replace-macro    sym->NumArgs >= 0
  506.  *
  507.  *  Must understand parenthesis...
  508.  *
  509.  *  NOTE:   In scanning a macro if we reach EOF and expect an open paren we
  510.  *        may go up a cpp level to continue the scan.
  511.  *
  512.  *  #define dec(var) ((var)--)
  513.  *  #define apply(func) (func(Glob))
  514.  *  apply(dec);
  515.  *
  516.  *        This can get tricky.  Basically, we pull the rug from under
  517.  *        previous levels of CPP().  Thus, CPP() must be very careful in
  518.  *        this regard.
  519.  *
  520.  *  #define GAG(a,b)    (a,b)
  521.  *  GAG(GAG(1,2),3)
  522.  *
  523.  *        Theoretically the macro arguments are supposed to be evaulated
  524.  *        first to allow this type of nesting.  But, we evaluate bottom
  525.  *        up!  To make this work right when a lower level macro's args
  526.  *        are evaulated the higher level macro names must be RE-ENABLED!
  527.  *
  528.  *
  529.  *  This routine must return in index relative to the original PushBase
  530.  *  regardless of any data it pulls from higher level pushbase's
  531.  */
  532.  
  533. long
  534. HandleSymbol(sym, base, i, max)
  535. Sym *sym;
  536. ubyte *base;
  537. long i;
  538. long max;
  539. {
  540.     Include *push;
  541.     short oldType = sym->Type;
  542.     short creType = 0;
  543.     short save_fls;
  544.  
  545.     {
  546.        long it = i;
  547.        push = PrepareSymbolArgs(sym, base, &it, max);
  548.        if (push == NULL) return(it);
  549.     }
  550.  
  551.     /*
  552.      *    If pushing a macro argument for replace we must enable the macro
  553.      *    it came from.  This allows MAX(MAX(1,2),3) while disallowing loop
  554.      *    conditions, i.e.    #define BAR(x)  BAR(1,x)
  555.      */
  556.  
  557.     if (sym->Type & SF_MACROARG)
  558.     {
  559.     if (sym->Creator == NULL)
  560.         cerror(EFATAL_SOFTWARE_ERROR_CREATOR);
  561.     creType = sym->Creator->Type;
  562.     sym->Creator->Type &= ~SF_RECURSE;
  563.     }
  564.  
  565.     if (sym->Type & SF_STRINGIZE) {
  566.     ++GlobalStringize;
  567.     fputc('\"', Fo);
  568.     }
  569.  
  570.     save_fls = ForceLineSpec;
  571.     ForceLineSpec = 0;
  572.  
  573.     PushBase->Index = cpp(PushBase->Index, PushBase->Level + 1,
  574.               sym->SymName, NULL, sym->Text, sym->TextLen);
  575.  
  576.     ForceLineSpec = save_fls;
  577.  
  578.     i = push->Index;
  579.  
  580.     if (sym->Type & SF_STRINGIZE) {
  581.     --GlobalStringize;
  582.     fputc('\"', Fo);
  583.     }
  584.  
  585.     if (sym->Type & SF_MACROARG)
  586.     sym->Creator->Type = creType;
  587.  
  588.     dbprintf(("(macro-return)"));
  589.  
  590.     if (sym->NumArgs >= 0) {    /*  undef symbol args symbols        */
  591.     short j;
  592.     for (j = 0; j < sym->NumArgs; ++j) {
  593.         if (UndefSymbol(sym->Args[j], sym->ArgsLen[j]) == 0)
  594.         cerror(EFATAL_SOFTWARE_ERROR_MACRO, sym->SymName, sym->Args[j]);
  595.     }
  596.     }
  597.     sym->Type = oldType;
  598.     push->Index = i;
  599.     return(PushBase->Index);
  600. }
  601.